package fs

// A simple in-memory read-only filesystem.
// Paths use '/' separators. Directories are implicit when entries include them.

type Entry struct {
    Path string
    Data []byte
}

type RamFS struct {
    files map[string][]byte
}

func NewRamFS(entries []Entry) *RamFS {
    m := make(map[string][]byte, len(entries))
    for _, e := range entries {
        // Normalize: ensure leading slash
        p := normalize(e.Path)
        m[p] = e.Data
    }
    return &RamFS{files: m}
}

func normalize(p string) string {
    if p == "" {
        return "/"
    }
    // ensure leading slash
    if p[0] != '/' {
        p = "/" + p
    }
    // drop trailing slash (except root)
    if len(p) > 1 && p[len(p)-1] == '/' {
        p = p[:len(p)-1]
    }
    return p
}

// List returns entries immediately under dir.
func (r *RamFS) List(dir string) ([]FileInfo, bool) {
    dir = normalize(dir)
    if dir != "/" && r.files[dir] != nil {
        // dir is a file, not a directory
        return nil, false
    }
    seen := map[string]bool{}
    out := []FileInfo{}
    prefix := dir
    if prefix != "/" {
        prefix += "/"
    }
    for p, data := range r.files {
        if p == dir {
            // exact file named as dir (should not happen)
            continue
        }
        if !hasPrefix(p, prefix) {
            continue
        }
        // take component after prefix up to next '/'
        rest := p[len(prefix):]
        name := rest
        isDir := false
        for i := 0; i < len(rest); i++ {
            if rest[i] == '/' {
                name = rest[:i]
                isDir = true
                break
            }
        }
        key := prefix + name
        if !seen[key] {
            seen[key] = true
            if isDir {
                out = append(out, FileInfo{Name: name, IsDir: true, Size: 0})
            } else {
                out = append(out, FileInfo{Name: name, IsDir: false, Size: len(data)})
            }
        }
    }
    return out, true
}

// ReadFile returns file contents by absolute path.
func (r *RamFS) ReadFile(path string) ([]byte, bool) {
    path = normalize(path)
    b, ok := r.files[path]
    if !ok {
        return nil, false
    }
    return b, true
}

func hasPrefix(s, pre string) bool {
    if len(pre) > len(s) {
        return false
    }
    for i := 0; i < len(pre); i++ {
        if s[i] != pre[i] {
            return false
        }
    }
    return true
}